package org.sdnstproject.interlayer.OF13Protocal;

import java.util.Random;

import org.projectfloodlight.openflow.types.U16;
import org.projectfloodlight.openflow.types.U32;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;

public class FuGroupMod {
	private static final Logger log = LoggerFactory.getLogger(FuGroupMod.class);
    public byte version = (byte)4;
    public byte type = (byte)15;
    public short length = (short)16;//MINIMUM_LENGTH = 16
    public long xid = 0x0L;
    public short command = 0x1;
    /*public final static byte ALL_VAL = (byte) 0x0;
    public final static byte SELECT_VAL = (byte) 0x1;
    public final static byte INDIRECT_VAL = (byte) 0x2;
    public final static byte FF_VAL = (byte) 0x3;
     * */
    public byte groupType;//OFGroupType TODO
    public int group;//OFGroup TODO
    public byte[] buckets = new byte[new Random().nextInt(40)+40];//TODO
	
    public FuGroupMod() {
    	
    }
    
    public FuGroupMod setXid(long xid) {
		this.xid = xid;
		return this;
	}
    
    private byte[] commands = new byte[] {0,1,2,3};
    public FuGroupMod setField(String field, String value) {
		switch (field) {
		case "version":
			this.version = Byte.parseByte(value);
			break;
		case "type":
			this.type = Byte.parseByte(value);
			break;
		case "length":
			this.length = Short.parseShort(value);
			break;
		case "xid":
			this.xid = Long.parseLong(value);
			break;
		case "command":
			if(value.equals("random")) {
				this.command = commands[new Random().nextInt(4)];
				break;
			}
			this.command = Byte.parseByte(value);
			break;
		case "groupType":
			this.groupType = Byte.parseByte(value);
			break;
		case "group":
			this.group = Integer.parseInt(value);
			break;
		case "buckets":
			this.buckets = new byte[new Random().nextInt(40)+40];//TODO modify the random bound value.
			new Random().nextBytes(buckets);
			break;
		}
		return this;
	}
    
	public ByteBuf writeTo() {
		ByteBuf bb = Unpooled.directBuffer();
        int startIndex = bb.writerIndex();
        // fixed value property version = 4
        bb.writeByte(version);
        // fixed value property type = 15
        bb.writeByte(type);
        // length is length of variable message, will be updated at the end
        int lengthIndex = bb.writerIndex();
        bb.writeShort(U16.t(0));

        bb.writeInt(U32.t(xid));
        // fixed value property command = 1
        bb.writeShort(command);
        bb.writeByte(groupType);
        // pad: 1 bytes
        bb.writeZero(1);
        bb.writeInt(group);
        bb.writeBytes(buckets);

        // update length field
        length = (short)(bb.writerIndex() - startIndex);
        bb.setShort(lengthIndex, length);
        return bb;
    }
	
	@Override
    public String toString() {
        StringBuilder b = new StringBuilder("OFGroupModifyVer13(");
        b.append("version=").append(version);
        b.append(", ");
        b.append("type=").append(type);
        b.append(", ");
        b.append("length=").append(length);
        b.append(", ");
        b.append("xid=").append(xid);
        b.append(", ");
        b.append("groupType=").append(groupType);
        b.append(", ");
        b.append("group=").append(group);
        b.append(", ");
        b.append("buckets=").append(buckets);
        b.append(")");
        return b.toString();
    }
}
